package com.mlx.meng.author;

import com.mlx.meng.tool.DataPermissionException;
import com.mlx.meng.verify.DataPermissionRowVerification;
import com.mlx.meng.tool.DataPermissionProperties;
import com.mlx.meng.tool.DataPermissionUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public abstract class AbstractDataPermissionRowAuthorization<T> extends WhiteListCollector{

    @Autowired
    private DataPermissionProperties properties;

    protected final Log logger = LogFactory.getLog(getClass());

    protected abstract Collection<T> listUserDataPermissionRow();

    public DataPermissionRowVerification getDataPermissionRow(){

        DataPermissionRowVerification rowVerification = new DataPermissionRowVerification();

        Collection<T> objectCollection = listUserDataPermissionRow();
        if (DataPermissionUtil.isEmpty(objectCollection)){
            return rowVerification;
        }

        // 获取行数据权限类型
        Iterator<T> iterator = objectCollection.iterator();
        Object next = iterator.next();
        Class<?> aClass = next.getClass();

        Field tableNameField = null;
        Field fieldNameField = null;
        Field permissionsField = null;

        try {
            tableNameField = aClass.getDeclaredField(properties.getTableName());
        } catch (NoSuchFieldException e) {
            throw new DataPermissionException("数据权限异常：构建行数据权限验证器时发现行数据权限对象没有属性映射指定的【%s】属性，请在配置文件中配置data.tableName为正确属性名称", properties.getTableName());
        }
        try {
            fieldNameField = aClass.getDeclaredField(properties.getFieldName());
        } catch (NoSuchFieldException e) {
            throw new DataPermissionException("数据权限异常：构建行数据权限验证器时发现行数据权限对象没有属性映射指定的【%s】属性，请在配置文件中配置data.fieldName为正确属性名称", properties.getFieldName());
        }
        try {
            permissionsField = aClass.getDeclaredField(properties.getPermissions());
        } catch (NoSuchFieldException e) {
            throw new DataPermissionException("数据权限异常：构建行数据权限验证器时发现行数据权限对象没有属性映射指定的【%s】属性，请在配置文件中配置data.permissions为正确属性名称", properties.getPermissions());
        }

        tableNameField.setAccessible(true);
        fieldNameField.setAccessible(true);
        permissionsField.setAccessible(true);

        for (Object obj : objectCollection){

            String tableName = null;
            String fieldName = null;
            String permissions = null;
            try {
                tableName = tableNameField.get(obj).toString();
                fieldName = fieldNameField.get(obj).toString();
                permissions = permissionsField.get(obj).toString();
            } catch (IllegalAccessException e) {
                throw new DataPermissionException("数据权限异常：获取行数据权限的tableName,fieldName,permissions属性时，无属性访问权限");
            }

            rowVerification.put(tableName, fieldName, permissions);
        }

        return rowVerification;
    }

    public void dataFilter(Collection<?> dataCollection, String tableName, String[] foreignKeys){

        long startTime = System.currentTimeMillis();

        if (DataPermissionUtil.isEmpty(dataCollection)){
            long endTime = System.currentTimeMillis();
            logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
            return;
        }

        if (isInWhiteList()){
            long endTime = System.currentTimeMillis();
            logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
            return;
        }

        DataPermissionRowVerification verification = getDataPermissionRow();
        DataPermissionRowVerification.DataPermissionRowEntityVerification entityVerification = verification.buildEntityDataPermissionRow(tableName, foreignKeys);

        // 没有数据权限就没有数据
        if (entityVerification.isNotExistDataPermission()){
            dataCollection.clear();
            long endTime = System.currentTimeMillis();
            logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
            return;
        }

        // 获取数据类型
        Iterator<?> iterator1 = dataCollection.iterator();
        Object next = iterator1.next();
        Class<?> aClass = next.getClass();

        // 获取数据类型的属性集合
        Map<String, Field> fieldMap = DataPermissionUtil.gainClassField(aClass);
        // 获取所有的权限字段
        Set<String> permissionField = entityVerification.getPermissionField();
        // 检查数据类型是否拥有对应权限字段的属性
        for (String k : permissionField){
            if (!(fieldMap.containsKey(k))){
                throw new DataPermissionException("返回数据的数据类型不存在权限字段【%s】指定的属性", k);
            }
        }

        // 过滤数据
        dataCollection.removeIf( data -> {
            try {
                return entityVerification.isNotDataPermission(data, fieldMap);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            throw new DataPermissionException("数据过滤removeIf异常");
        });

        long endTime = System.currentTimeMillis();
        logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
    }

    public void dataFilter(Collection<?> dataCollection, String tableName, String[] foreignKeys, String getMethodName, Class<?> methodParamType){

        long startTime = System.currentTimeMillis();
        if (DataPermissionUtil.isEmpty(dataCollection)){
            long endTime = System.currentTimeMillis();
            logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
            return;
        }
        if (isInWhiteList()){
            long endTime = System.currentTimeMillis();
            logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
            return;
        }

        DataPermissionRowVerification verification = getDataPermissionRow();
        DataPermissionRowVerification.DataPermissionRowEntityVerification entityVerification = verification.buildEntityDataPermissionRow(tableName, foreignKeys);

        // 没有数据权限就没有数据
        if (entityVerification.isNotExistDataPermission()){
            dataCollection.clear();
            long endTime = System.currentTimeMillis();
            logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
            return;
        }

        // 获取数据类型
        Iterator<?> iterator1 = dataCollection.iterator();
        Object next = iterator1.next();
        Class<?> aClass = next.getClass();


        try {
            // 获取getMethodName指定的属性值获取方法
            Method method = aClass.getDeclaredMethod(getMethodName, methodParamType);
            // 过滤数据
            dataCollection.removeIf( data -> {
                try {
                    return entityVerification.isNotDataPermission(data, method);
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
                throw new DataPermissionException("数据过滤removeIf异常");
            });

        } catch (NoSuchMethodException e) {
            throw new DataPermissionException("数据权限异常：过滤map类型的行数据权限时，返回的数据没有getMethodName指定的【%s】方法", getMethodName);
        }

        long endTime = System.currentTimeMillis();

        logger.debug("行数据权限过滤时间：" + (endTime - startTime) + "ms");
    }
}
